package Cinema.Tests;

import static org.junit.Assert.*;

import org.custommonkey.xmlunit.DetailedDiff;
import org.custommonkey.xmlunit.Diff;
import org.custommonkey.xmlunit.Difference;
import org.junit.Before;
import org.junit.Test;
import org.w3c.dom.Document;

import Utils.XmlParseHelper;

import java.util.Date;
import java.util.List;

import Cinema.CinemaEntities.IShow;
import Cinema.CinemaEntities.Location;
import Cinema.CinemaEntities.Movie;
import Cinema.CinemaEntities.Show;
import Cinema.CinemaEntities.Theater;
import Cinema.DataLayer.XmlBackup;
import Exceptions.CinemaException;

public class ShowTest implements IXmlParsableTest{

	IShow show;
	String movieName;
	Date date;
	
	@SuppressWarnings("deprecation")
	@Before
	public void StartOver()
	{
		movieName = "Piter pen";
		date = new Date(4,4,2013,22,45,0);
		Theater theater;
		Movie movie = new Movie("Piter pen","action");
		try {
			theater = new Theater("test", new Location(0, 0), 3, 4);
			show = new Show(date, theater, movie,5,5);
		} catch (CinemaException e) {
			e.printStackTrace();
		}
	}
	
	@Test
	public void testShow() throws CinemaException 
	{
		assertNotNull(show.OrderPlaces(4));
		assertNotNull(show.OrderPlaces(4));
		assertNotNull(show.OrderPlaces(4));
		assertNull(show.OrderPlaces(1));
		assertTrue(show.checkOrderPossibility(1) == false);
		Integer[] temp = {0,2};
		show.freeSeats(temp);
		temp[0] = 1; temp[1] = 2;
		show.freeSeats(temp);
		assertTrue(show.checkOrderPossibility(2) == false);
		assertTrue(show.checkOrderPossibility(1) == true);
		assertNotNull(show.OrderPlaces(1));
		assertTrue(show.checkOrderPossibility(1) == true);
		assertNotNull(show.OrderPlaces(1));
		assertTrue(show.checkOrderPossibility(1) == false);
	}

	/**
	 * Test get movie getter
	 */
	@Test
	public void testGetMovieName() 
	{
		String result = show.getMovieName();
		assertTrue(result.equals(movieName));
	}

	/**
	 * Test get show getter
	 */
	@Test
	public void testGetShowDate() 
	{
		Date result = show.getShowDate();
		assertTrue(result.equals(date));
	}

	/**
	 * Test free seats - passing null argument
	 */
	@Test  (expected = NullPointerException.class)
	public void testFreeSeats_nullArgument() throws CinemaException 
	{
		show.freeSeats(null);
	}
	
	/**
	 * Test free seats - tring to free illegal places
	 */
	@Test  (expected = CinemaException.class)
	public void testFreeSeats_testIllegalPlaces() throws CinemaException 
	{
		show.OrderPlaces(4);
		show.OrderPlaces(4);
		show.OrderPlaces(4);
		Integer[] places = {-1,1,2,3};
		show.freeSeats(places);
	}
	
	/**
	 * Test free seats - try to free empty seats
	 */
	@Test  (expected = CinemaException.class)
	public void testFreeSeats_testEmptyseats() throws CinemaException 
	{
		Integer[] places = {2,1,2,3};
		show.freeSeats(places);
	}
	
	/**
	 * Test free seats - testing regular case
	 */
	@Test 
	public void testFreeSeats_regularSenario() throws CinemaException 
	{
		Integer[] places1 = show.OrderPlaces(4);
		Integer[] places2 = show.OrderPlaces(4);
		Integer[] places3 = show.OrderPlaces(4);
		show.freeSeats(places2);
		show.freeSeats(places3);
		show.freeSeats(places1);
	}

	/**
	 * private function for checking the result of the order
	 * @param arr - the order.
	 */
	private Boolean CheckOrder(Integer[] arr)
	{
		if(arr.length < 2)
			return false;
		for (int i = 1; i < arr.length - 2; i++)
			if (arr[i] + 1 != arr[i+1])
				return false;
		return true;
	}
	
	/**
	 * Test order places - testing regular case
	 */
	@Test
	public void testOrderPlaces_regularSenrio() 
	{
		Integer[] result;
		assertNotNull(result = show.OrderPlaces(4));
		assertTrue(CheckOrder(result));
		assertNull(result = show.OrderPlaces(5));
		assertNotNull(result = show.OrderPlaces(4));
		assertTrue(CheckOrder(result));
		assertNotNull(result = show.OrderPlaces(1));
		assertTrue(CheckOrder(result));
		assertNull(result = show.OrderPlaces(4));
		assertNotNull(result = show.OrderPlaces(2));
		assertTrue(CheckOrder(result));
		assertNotNull(result = show.OrderPlaces(1));
		assertTrue(CheckOrder(result));
	}
	
	/**
	 * Test order places - testing passing illegal arguments
	 */
	@Test (expected = IllegalArgumentException.class)
	public void testOrderPlaces_testPassingIllegalArgument() 
	{
		show.OrderPlaces(0);
	}

	/**
	 * Test check order possibility - testing regular case
	 */
	@Test
	public void testCheckOrderPossibility_testRegularSenrio()
	{
		assertTrue(show.checkOrderPossibility(1));
		assertTrue(show.checkOrderPossibility(5) == false);
		assertNotNull(show.OrderPlaces(4));
		assertNotNull(show.OrderPlaces(4));
		assertNotNull(show.OrderPlaces(4));
		assertTrue(show.checkOrderPossibility(1) == false);
	}
	
	/**
	 * Test order places - testing passing illegal arguments
	 */
	@Test (expected = IllegalArgumentException.class)
	public void testCheckOrderPossibility_testPassingIllegalArgument()
	{
		show.checkOrderPossibility(0);
	}

	/**
	 * Test xml parse
	 */
	@Test
	@Override
	public void test_getXml() throws CinemaException{
		//creating test doc
		TestShow show = new TestShow(new Date(1234567890L), new Theater("", null, 3, 9), "The Rock", "Action",40,60);
		Boolean[][] seatMap = {{false,false,false,false,false,false,false,false,false},
								{false,true,false,true,true,true,false,true,true},
								{true,true,true,true,false,false,true,false,false}};
		show.setSeats(seatMap);
		show.setId(1279);
		
		Document testDoc = XmlBackup.createDocFromXmlParsableObject(show);
		
		//create control doc
		Document controlDoc = XmlParseHelper.getDocumentFromFile(".\\tests\\testXml\\ShowTest.xml");
		
		Diff diff = new Diff(controlDoc, testDoc);
		DetailedDiff detailedDiff = new DetailedDiff(diff);
		
		//for debugging
		@SuppressWarnings("unchecked")
		List<Difference> difList = detailedDiff.getAllDifferences();
		for (Difference difference : difList) {
			String discription = difference.getDescription();
			discription.toString();
		}
		
		boolean isEq = diff.similar();
		
		assertTrue(isEq);
	}
	
	/**
	 * Test xml init
	 */
	@Test
	@Override
	public void test_initFromXml() throws CinemaException{
		//control object
		TestShow contShow = new TestShow(new Date(666666666L), new Theater("", null, 4, 8), "Casablanca", "Drama",7,9);
		Boolean[][] seatMap = {{true,true,true,true,true,true,true,true},
				{false,true,false,true,true,true,false,true},
				{true,true,true,true,false,false,true,true},
				{false,false,false,false,true,true,true,true}};
		contShow.setSeats(seatMap);
		contShow.setId(12345679);
		
		Show testShow = new Show(new Theater("", null, 4, 8), XmlParseHelper.getDocumentFromFile(".\\tests\\testXml\\ShowTest2.xml").getDocumentElement());
		
		boolean isEq = testShow.checkEquals(contShow);
		
		assertTrue(isEq);
	}
	
	private class TestShow extends Show{
		public TestShow(Date date,Theater theater, String movieName, String movieGenre, int adultPrice, int childPrice) {
			super(date, theater, movieName, movieGenre, adultPrice, childPrice);
		}
		
		public void setId(long id){
			myID = id;
		}
		
		public void setSeats(Boolean[][] seats){
			this.seats = seats;
		}
	}
}
